<?php

namespace Xapi\Kernel;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller;
use Illuminate\Support\Str;

class RouteDispatch extends Controller
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    public $controller;

    public function __construct()
    {
        $this->initController();
        $this->resolveMiddleware();
    }

    public function __invoke()
    {
        return request()->route()->controllerDispatcher()->dispatch(
            request()->route(), $this->controller, $this->controller('method')
        );
    }

    public function controller($attribute = null)
    {
        if ($attribute) return $this->controller->{$attribute};
        return $this->controller;
    }

    //初始化控制器实例
    public function initController()
    {
        $this->controller = app($this->getController());
    }

    //获取控制器
    public function getController()
    {
        $prefix = config('xapi.controller.prefix', 'App\Http\Controllers');
        $middle = config('xapi.controller.middle', '');
        $suffix = config('xapi.controller.suffix', 'Controller');
        $module = Str::studly(request()->route('module'));
        $action = Str::studly(request()->route('action'));
        $class = $prefix . '\\' . $module . '\\' . $middle . '\\' . $action . $suffix;
        return $this->formatClass($class);
    }

    //格式化类名
    public function formatClass($class)
    {
        return str_replace('\\\\', '\\', $class);
    }

    //实现控制器中间件
    public function resolveMiddleware()
    {
        $this->middleware($this->getMiddlewareArray());
    }

    //获取中间件
    public function getMiddlewareArray()
    {
        $global = config('xapi.middleware', null);
        $global = is_null($global) ? collect(['api']) : collect($global);
        $region = collect($this->controller('middleware'));
        return $global->concat($region)->unique()->filter(function ($item) {
            return !in_array($item, $this->controller('except_middleware'));
        })->values()->all();
    }
}
